package com.example.glgk.service.gather;

import com.example.glgk.dto.EscalationDeptData;
import com.example.glgk.dto.QueryEscalation;
import com.example.glgk.dto.gather.ClinicalGatherDataDto;
import com.example.glgk.dto.gather.DeptEscalationDataDto;
import com.example.glgk.dto.gather.HeaderDataDto;
import com.example.glgk.entity.DepartmentIndicatorEntity;
import com.example.glgk.entity.ElementDataEntity;
import com.example.glgk.entity.IndicatorDataEntity;
import com.example.glgk.mapper.*;
import com.example.glgk.utils.Calculator;
import com.example.glgk.utils.CalculatorUtils;
import com.example.glgk.utils.ExcelUtilsPlus;
import com.example.glgk.utils.PageUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lxk
 */
@Service
@Slf4j
public class ClinicalGatherService {

    @Autowired
    IndicatorDataMapper indicatorDataMapper;

    @Autowired
    ElementDataMapper elementDataMapper;

    @Autowired
    ElementDataDayMapper elementDataDayMapper;

    @Autowired
    ElementDataMonthMapper elementDataMonthMapper;

    @Autowired
    GatherCommonService gatherCommonService;

    @Autowired
    DeptGatherService deptGatherService;

    @Autowired
    private ReportMapper reportMapper;

    @Autowired
    private ReportTaskMapper reportTaskMapper;

    private static String regex = "^-?[0-9]+(\\.[0-9]*)?$";


    public List<ClinicalGatherDataDto> queryClinicalData(QueryEscalation queryEscalation) {
        PageHelper.startPage(queryEscalation.getPageNumber(), queryEscalation.getPageSize());
        return queryData(queryEscalation);
    }

    /**
     * 计算同比日期及环比日期
     *
     * @param queryEscalation
     */
    public void fillRelationTime(QueryEscalation queryEscalation) {
        //获取参数中需要查询的时间
        List<String> times = queryEscalation.getTimes();
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(times)) {
            throw new RuntimeException("查询时间为空");
        }
        List<String> yoyTimes = getYoyTime(times);//获取同比时间集合
        List<String> momTimes = getLinkTime(times);//获取环比时间集合

        List<String> allTimes = new ArrayList<>();
        allTimes.addAll(times);
        allTimes.addAll(yoyTimes);
        allTimes.addAll(momTimes);

        queryEscalation.setYoyTimes(yoyTimes);
        queryEscalation.setMomTimes(momTimes);
        queryEscalation.setAllTimes(allTimes.stream().distinct().collect(Collectors.toList()));
    }

    /**
     * 计算同比时间
     *
     * @param
     * @param
     * @return
     */
    public List<String> getYoyTime(List<String> times) {
        List<String> lastYearDates = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        boolean isWholeMonth;
        // 使用流式操作按年份和月份分组,分组后的map中 键是年和月，如2024-01， 值是List集合，存的是相同年月的字符串,同时指定插入顺序，采用LinkedHashMap
        Map<String, List<String>> groupedDates = times.stream().collect(Collectors.groupingBy(date -> date.substring(0, 7), LinkedHashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<String>> entry : groupedDates.entrySet()) {
            List<String> groupTimes = entry.getValue();
            // 判断是否是一整个月
            isWholeMonth = isWholeMonth(groupTimes);
            for (String currentDate : groupTimes) {
                LocalDate date = LocalDate.parse(currentDate, formatter);
                if (isWholeMonth) {
                    int lastYearMonthLength = date.minusYears(1).lengthOfMonth(); // 获取去年同月的天数
                    LocalDate lastYearStartDate = LocalDate.of(date.getYear() - 1, date.getMonth(), 1); // 去年同月的第一天
                    for (int i = 0; i < lastYearMonthLength; i++) {
                        lastYearDates.add(lastYearStartDate.plusDays(i).format(formatter));
                    }
                    break;
                } else {
                    LocalDate lastYearDate = date.minusYears(1);
                    lastYearDates.add(lastYearDate.format(formatter));
                }
            }
        }


        return lastYearDates;
    }

    /**
     * 计算环比时间
     *
     * @param
     * @param
     * @return
     */
    public List<String> getLinkTime(List<String> times) {
        List<String> lastMonthDates = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        boolean isWholeMonth;
        // 使用流式操作按年份和月份分组,分组后的map中 键是年和月，如2024-01， 值是List集合，存的是相同年月的字符串,同时指定插入顺序，采用LinkedHashMap
        Map<String, List<String>> groupedDates = times.stream().collect(Collectors.groupingBy(date -> date.substring(0, 7), LinkedHashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<String>> entry : groupedDates.entrySet()) {
            List<String> groupTimes = entry.getValue();
            // 判断是否是一整个月
            isWholeMonth = isWholeMonth(groupTimes);

            LocalDate firstDate = LocalDate.parse(groupTimes.get(0), formatter);
            LocalDate lastDate = LocalDate.parse(groupTimes.get(groupTimes.size() - 1), formatter);

            LocalDate lastMonthStartDate;
            LocalDate lastMonthEndDate;
            if (isWholeMonth) {
                lastMonthStartDate = firstDate.minusMonths(1);
                int lastMonthLength = lastMonthStartDate.lengthOfMonth();
                for (int i = 0; i < lastMonthLength; i++) {
                    lastMonthDates.add(lastMonthStartDate.plusDays(i).format(formatter));
                }
            } else {
                lastMonthStartDate = firstDate.minusMonths(1);
                lastMonthEndDate = lastDate.minusMonths(1);

                for (LocalDate date = lastMonthStartDate; !date.isAfter(lastMonthEndDate); date = date.plusDays(1)) {
                    lastMonthDates.add(date.format(formatter));
                }
            }
        }
        return lastMonthDates;
    }

    private static boolean isWholeMonth(List<String> times) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate firstDate = LocalDate.parse(times.get(0), formatter);
        LocalDate lastDate = LocalDate.parse(times.get(times.size() - 1), formatter);
        if (firstDate.getDayOfMonth() != 1) {
            return false;
        }
        int daysInMonth = firstDate.lengthOfMonth();
        return lastDate.getDayOfMonth() == daysInMonth;
    }

    /**
     * 计算环比值或者同比值
     *
     * @param currentValue
     * @param previousValue
     * @return
     */
    public String calculateGrowthRate(String currentValue, String previousValue) {
        if (currentValue.equals("-") || previousValue.equals("-")) {
            return "-"; // 当值为 "-" 时，无法计算增长率，直接返回 "-"
        }

        double current = Double.parseDouble(currentValue);
        double previous = Double.parseDouble(previousValue);

        if (previous == 0.0) {
            return "0"; // 当前值为非零而上一期值为零时,直接返回0，无意义
        }

        double growthRate = (current - previous) / previous;
        return String.format("%.2f", growthRate); // 将增长率转换为字符串，并返回,保留两位小数，四舍五入
    }


    public PageUtils queryClinicalIndicatorData(QueryEscalation queryEscalation) {
        List<String> times = queryEscalation.getTimes();
        List<ClinicalGatherDataDto> result = new ArrayList<>();

        Page<IndicatorDataEntity> page = PageHelper.startPage(queryEscalation.getPageNumber(), queryEscalation.getPageSize());
        //查询指标表中的所有的关于上报信息的元素定义公式
        List<IndicatorDataEntity> list = indicatorDataMapper.selectAll(queryEscalation);

        fillRelationTime(queryEscalation);

        //对所有涉及到的id进行去重
        List<String> elementIds = gatherCommonService.getAllElementIds(list);
        //查询元素定义表，确定元素数据来源 天表、月表、手填表等
        List<ElementDataEntity> elementDataEntities = elementDataMapper.query(elementIds);
        //分别得出天表，月表，手填表的元素数据
        List<ElementDataEntity> dayTable = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && "1".equals(s.getDataTable())).collect(Collectors.toList());
        List<ElementDataEntity> monthTable = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && "2".equals(s.getDataTable())).collect(Collectors.toList());
        List<ElementDataEntity> handTable = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && "3".equals(s.getDataTable())).collect(Collectors.toList());


        List<DepartmentIndicatorEntity> departmentIndicatorEntityList = new ArrayList<>();// 存放当前时间的所有的天表、月表、手填表数据
        List<DepartmentIndicatorEntity> departmentIndicatorEntityMomList = new ArrayList<>();// 存放环比时间的所有的天表、月表、手填表数据
        List<DepartmentIndicatorEntity> departmentIndicatorEntityYoyList = new ArrayList<>();// 存放同比时间的所有的天表、月表、手填表数据

        //妇科和产科特殊
        String wardName = queryEscalation.getUserInfo().getWardName();


        //查出天表数据 求的是指定时间区间的 天表数据之和
        if (!org.springframework.util.CollectionUtils.isEmpty(dayTable)) {
            queryEscalation.setElementIds(dayTable.stream().map(ElementDataEntity::getId).collect(Collectors.toList()));
            int size = queryEscalation.getTimes().size();
            queryEscalation.setStartTime(queryEscalation.getTimes().get(0));
            queryEscalation.setEndTime(queryEscalation.getTimes().get(size - 1));

            List<DepartmentIndicatorEntity> dayData = new ArrayList<>();

            if (wardName.equals("妇科") || wardName.equals("产科")) {
                dayData = elementDataDayMapper.queryClinicalSpecialGroupByDay(queryEscalation); //天表数据
            } else {
                dayData = elementDataDayMapper.queryClinicalGroupByDay(queryEscalation); //天表数据
            }
            departmentIndicatorEntityList.addAll(dayData);

            size = queryEscalation.getMomTimes().size();
            queryEscalation.setStartTime(queryEscalation.getMomTimes().get(0));
            queryEscalation.setEndTime(queryEscalation.getMomTimes().get(size - 1));

            List<DepartmentIndicatorEntity> dayMomData = new ArrayList<>();
            if (wardName.equals("妇科") || wardName.equals("产科")) {
                dayMomData = elementDataDayMapper.queryClinicalSpecialGroupByDay(queryEscalation); //天表数据
            } else {
                dayMomData = elementDataDayMapper.queryClinicalGroupByDay(queryEscalation); //天表数据
            }
            departmentIndicatorEntityMomList.addAll(dayMomData);

            size = queryEscalation.getYoyTimes().size();
            queryEscalation.setStartTime(queryEscalation.getYoyTimes().get(0));
            queryEscalation.setEndTime(queryEscalation.getYoyTimes().get(size - 1));
            List<DepartmentIndicatorEntity> dayYoyData = new ArrayList<>();
            if (wardName.equals("妇科") || wardName.equals("产科")) {
                dayYoyData = elementDataDayMapper.queryClinicalSpecialGroupByDay(queryEscalation); //天表数据
            } else {
                dayYoyData = elementDataDayMapper.queryClinicalGroupByDay(queryEscalation); //天表数据
            }
            departmentIndicatorEntityYoyList.addAll(dayYoyData);
        }
        List<String> groupTimes;
        //查出月表数据 求的是指定时间区间的 月表数据之和（月表每个月数据就一条 求和与不求和没有区别）
        if (!org.springframework.util.CollectionUtils.isEmpty(monthTable)) {

            queryEscalation.setElementIds(monthTable.stream().map(ElementDataEntity::getId).collect(Collectors.toList()));
            groupTimes = times.stream().map(time -> time.substring(0, 7)).distinct().collect(Collectors.toList());
            queryEscalation.setGroupTimes(groupTimes);
            List<DepartmentIndicatorEntity> monthData = elementDataMonthMapper.queryEscalationNew(queryEscalation); //月表数据
            departmentIndicatorEntityList.addAll(monthData);

            groupTimes = queryEscalation.getMomTimes().stream().map(time -> time.substring(0, 7)).distinct().collect(Collectors.toList());
            queryEscalation.setGroupTimes(groupTimes);
            List<DepartmentIndicatorEntity> monthMomData = elementDataMonthMapper.queryEscalationNew(queryEscalation); //月表数据
            departmentIndicatorEntityMomList.addAll(monthMomData);

            groupTimes = queryEscalation.getYoyTimes().stream().map(time -> time.substring(0, 7)).distinct().collect(Collectors.toList());
            queryEscalation.setGroupTimes(groupTimes);
            List<DepartmentIndicatorEntity> monthYoyData = elementDataMonthMapper.queryEscalationNew(queryEscalation); //月表数据
            departmentIndicatorEntityYoyList.addAll(monthYoyData);

        }

        //查出手填表数据 求的是指定时间区间的 手填表数据之和（手填表每个月数据就一条 求和与不求和没有区别）
        if (!org.springframework.util.CollectionUtils.isEmpty(handTable)) {
            queryEscalation.setElementIds(handTable.stream().map(ElementDataEntity::getId).collect(Collectors.toList()));

            groupTimes = times.stream().map(time -> time.substring(0, 7)).distinct().collect(Collectors.toList());
            queryEscalation.setGroupTimes(groupTimes);
            List<String> taskIds = reportTaskMapper.selectReportTasks(groupTimes, queryEscalation.getUserInfo().getWardName(), queryEscalation.getUserInfo().getParentDepartmentId());
            List<DepartmentIndicatorEntity> handTableData = new ArrayList<>();
            if (taskIds.size() > 0) {
                queryEscalation.setTaskIds(taskIds);
                handTableData = reportMapper.queryIndexValueNew(queryEscalation); //手填表数据
            }
            departmentIndicatorEntityList.addAll(handTableData);

            groupTimes = queryEscalation.getMomTimes().stream().map(time -> time.substring(0, 7)).distinct().collect(Collectors.toList());
            queryEscalation.setGroupTimes(groupTimes);
            taskIds = reportTaskMapper.selectReportTasks(groupTimes, queryEscalation.getUserInfo().getWardName(), queryEscalation.getUserInfo().getParentDepartmentId());
            List<DepartmentIndicatorEntity> handTableMomData = new ArrayList<>();
            if (taskIds.size() > 0) {
                queryEscalation.setTaskIds(taskIds);
                handTableMomData = reportMapper.queryIndexValueNew(queryEscalation); //手填表数据
            }
            departmentIndicatorEntityMomList.addAll(handTableMomData);

            groupTimes = queryEscalation.getYoyTimes().stream().map(time -> time.substring(0, 7)).distinct().collect(Collectors.toList());
            queryEscalation.setGroupTimes(groupTimes);
            taskIds = reportTaskMapper.selectReportTasks(groupTimes, queryEscalation.getUserInfo().getWardName(), queryEscalation.getUserInfo().getParentDepartmentId());
            List<DepartmentIndicatorEntity> handTableYoyData = new ArrayList<>();
            if (taskIds.size() > 0) {
                queryEscalation.setTaskIds(taskIds);
                handTableYoyData = reportMapper.queryIndexValueNew(queryEscalation); //手填表数据
            }
            departmentIndicatorEntityYoyList.addAll(handTableYoyData);

        }

        Map<String, List<DepartmentIndicatorEntity>> curMap = departmentIndicatorEntityList.stream().collect(Collectors.groupingBy(e -> e.getTime().substring(0, 7)));//当前时间的所有天数的指标值
        Map<String, List<DepartmentIndicatorEntity>> momMap = departmentIndicatorEntityMomList.stream().collect(Collectors.groupingBy(e -> e.getTime().substring(0, 7)));//环比时间的所有天数的指标值
        Map<String, List<DepartmentIndicatorEntity>> yoyMap = departmentIndicatorEntityYoyList.stream().collect(Collectors.groupingBy(e -> e.getTime().substring(0, 7)));//同比时间的所有天数的指标值

        groupTimes = times.stream().map(time -> time.substring(0, 7)).distinct().collect(Collectors.toList());
        for (IndicatorDataEntity entity : list) {
            //构建EscalationData对象
            ClinicalGatherDataDto escalationData = new ClinicalGatherDataDto();
            escalationData.setIndicatorName(entity.getIndexCode() + entity.getIndexName());
            escalationData.setUnit(entity.getIndexUnit());
            escalationData.setRow(entity.getRank());
            escalationData.setMfz(entity.getMfz() != 0 ? String.valueOf(entity.getMfz()) : "-");

            BigDecimal totalValue = new BigDecimal("0");
            BigDecimal beforeTotalValue = new BigDecimal("0");


            BigDecimal fzValue = new BigDecimal("0");
            BigDecimal fmValue = new BigDecimal("0");

            BigDecimal beforeFzValue = new BigDecimal("0");
            BigDecimal beforeFmValue = new BigDecimal("0");

            String unit = entity.getIndexUnit();

            for (String time : groupTimes) {
                List<DepartmentIndicatorEntity> curList = curMap.get(time);

                Map<String, String> mapValue = new HashMap<>();
                //把curList中id相同的进行累加，返回的还是一个list集合，然后放入到一个map中，计算当前time的指标值
                if (!org.springframework.util.StringUtils.isEmpty(curList)) {
                    mapValue = curList.stream().collect(Collectors.groupingBy(e -> String.format("${%s}", e.getId()), Collectors.collectingAndThen(Collectors.summingDouble(e -> Double.parseDouble(e.getElementNumber())), sum -> String.valueOf(sum))));
                }


                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
                YearMonth yearMonth = YearMonth.parse(time, formatter);
                YearMonth previousMonth = yearMonth.minusMonths(1);
                String momTime = previousMonth.format(formatter);

                List<DepartmentIndicatorEntity> momList = momMap.get(momTime);
                Map<String, String> mapMomValue = new HashMap<>();
                if (!org.springframework.util.StringUtils.isEmpty(momList)) {
                    mapMomValue = momList.stream().collect(Collectors.groupingBy(e -> String.format("${%s}", e.getId()), Collectors.collectingAndThen(Collectors.summingDouble(e -> Double.parseDouble(e.getElementNumber())), sum -> String.valueOf(sum))));
                }

                YearMonth previousYearSameMonth = yearMonth.minusYears(1);
                String yoyTime = previousYearSameMonth.format(formatter);

                List<DepartmentIndicatorEntity> yoyList = yoyMap.get(yoyTime);
                Map<String, String> mapYoyValue = new HashMap<>();
                if (!org.springframework.util.StringUtils.isEmpty(yoyList)) {
                    mapYoyValue = yoyList.stream().collect(Collectors.groupingBy(e -> String.format("${%s}", e.getId()), Collectors.collectingAndThen(Collectors.summingDouble(e -> Double.parseDouble(e.getElementNumber())), sum -> String.valueOf(sum))));
                }

                //解析当前指标的公式，通过元素值计算指标值
                String formula = entity.getCalculationFormulaId();
                String indexValue = Calculator.conversionToSting(formula, mapValue);
                String indexMomValue = Calculator.conversionToSting(formula, mapMomValue);
                String indexYoyValue = Calculator.conversionToSting(formula, mapYoyValue);

                //计算环比值：（当前值-环比时间值）/环比时间值
                String momValue = calculateGrowthRate(indexValue, indexMomValue);
                //计算同比值：（当前值-同比时间值）/同比时间值
                String yoyValue = calculateGrowthRate(indexValue, indexYoyValue);

                HeaderDataDto headerDataDto = new HeaderDataDto();
                headerDataDto.setIndicator(indexValue);
                headerDataDto.setMomValue(momValue);
                headerDataDto.setYoyValue(yoyValue);

                escalationData.getDynamicColumns().putIfAbsent(time, headerDataDto);

                if ("比值（×:1）".equals(unit) || "%".equals(unit)) {
                    if (StringUtils.isNotBlank(formula)) {

                        String[] item = formula.split("/");
                        if (item.length >= 2) {
                            String fzMula = item[0];
                            String fmMula = item[1];
                            String molecularValue = Calculator.conversionToSting(fzMula, mapValue);
                            String denominatorValue = Calculator.conversionToSting(fmMula, mapValue);
                            fzValue = new BigDecimal(molecularValue == "-" ? "0" : molecularValue).add(fzValue);
                            fmValue = new BigDecimal(denominatorValue == "-" ? "0" : denominatorValue).add(fmValue);

                            //去年分子分母值
                            String beforeMolecularValue = Calculator.conversionToSting(fzMula, mapYoyValue);
                            String beforeDenominatorValue = Calculator.conversionToSting(fmMula, mapYoyValue);
                            beforeFzValue = new BigDecimal(beforeMolecularValue == "-" ? "0" : beforeMolecularValue).add(beforeFzValue);
                            beforeFmValue = new BigDecimal(beforeDenominatorValue == "-" ? "0" : beforeDenominatorValue).add(beforeFmValue);
                        }
                    }
                }

                totalValue = new BigDecimal(indexValue == "-" ? "0" : indexValue).add(totalValue);
                beforeTotalValue = new BigDecimal(indexYoyValue == "-" ? "0" : indexYoyValue).add(beforeTotalValue);


            }

            if ("比值（×:1）".equals(unit) || "%".equals(unit)) {
                if (fmValue.compareTo(BigDecimal.ZERO) == 0) {
                    escalationData.setTotalValue("-");
                    escalationData.setYoyTotalValue("-");
                } else {
                    String totalValueStr = fzValue.divide(fmValue, 4, RoundingMode.HALF_UP).toString();
                    escalationData.setTotalValue(totalValueStr);

                    if (beforeFmValue.compareTo(BigDecimal.ZERO) == 0) {
                        escalationData.setYoyTotalValue("-");
                    }else{
                        String yoyTotalValueStr = beforeFzValue.divide(beforeFmValue, 4, RoundingMode.HALF_UP).toString();
                        String yoyTotalValue = calculateGrowthRate(totalValueStr, yoyTotalValueStr);
                        escalationData.setYoyTotalValue(yoyTotalValue);
                    }
                }
            } else if ("—".equals(unit)) {
                escalationData.setTotalValue("-");
                escalationData.setYoyTotalValue("-");
            } else {
                escalationData.setTotalValue(totalValue.toString());
                escalationData.setYoyTotalValue(calculateGrowthRate(totalValue.toString(), beforeTotalValue.toString()));
            }

            result.add(escalationData);
        }
        PageUtils pageUtils = new PageUtils(result, page.getTotal(), page.getPageSize(), page.getPageNum());
        return pageUtils;
    }

    public List<EscalationDeptData> queryGatherClinicalIndicatorData(QueryEscalation queryEscalation) {
        List<String> times = queryEscalation.getTimes();
        List<EscalationDeptData> result = new ArrayList<>();


        List<IndicatorDataEntity> list = indicatorDataMapper.queryMajorIndicator(queryEscalation);

        fillRelationTime(queryEscalation);

        //对所有涉及到的id进行去重
        List<String> elementIds = gatherCommonService.getAllElementIds(list);
        //查询元素定义表，确定元素数据来源 天表、月表、手填表等
        List<ElementDataEntity> elementDataEntities = elementDataMapper.query(elementIds);
        //分别得出天表，月表，手填表的元素数据
        List<ElementDataEntity> dayTable = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && "1".equals(s.getDataTable())).collect(Collectors.toList());
        List<ElementDataEntity> monthTable = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && "2".equals(s.getDataTable())).collect(Collectors.toList());
        List<ElementDataEntity> handTable = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && "3".equals(s.getDataTable())).collect(Collectors.toList());


        List<DepartmentIndicatorEntity> departmentIndicatorEntityList = new ArrayList<>();// 存放当前时间的所有的天表、月表、手填表数据

        //查出天表数据 求的是指定时间区间的 天表数据之和
        if (!org.springframework.util.CollectionUtils.isEmpty(dayTable)) {
            //查询今年天表数据
            queryEscalation.setElementIds(dayTable.stream().map(ElementDataEntity::getId).collect(Collectors.toList()));
            int size = queryEscalation.getTimes().size();
            queryEscalation.setStartTime(queryEscalation.getTimes().get(0));
            queryEscalation.setEndTime(queryEscalation.getTimes().get(size - 1));
            List<DepartmentIndicatorEntity> dayData = elementDataDayMapper.queryGatherClinicalGroupByDay(queryEscalation); //天表数据
            departmentIndicatorEntityList.addAll(dayData);
        }

        Map<String, List<DepartmentIndicatorEntity>> groupData = departmentIndicatorEntityList.stream().collect(Collectors.groupingBy(e -> e.getDeptName() != null ? e.getDeptName() : "unKnownDept"));
        List<String> depts = queryEscalation.getDeptNames();
        if (!org.springframework.util.StringUtils.isEmpty(depts)) {
            for (int i = 0; i < depts.size(); i++) {
                String deptName = depts.get(i);
                EscalationDeptData escalationData = new EscalationDeptData();
                escalationData.setProject(deptName);
                escalationData.setRow(i + 1);

                List<DepartmentIndicatorEntity> deptList = groupData.get(deptName);
                for (IndicatorDataEntity entity : list) {

                    Map<String, String> mapValue = new HashMap<>();
                    if (!org.springframework.util.StringUtils.isEmpty(deptList)) {
                        mapValue = deptList.stream().collect(Collectors.toMap(e -> "${" + e.getId() + "}", DepartmentIndicatorEntity::getElementNumber));
                    }

                    //解析当前指标的公式，通过元素值计算指标值
                    String formula = entity.getCalculationFormulaId();
                    String indexValue = Calculator.conversionToSting(formula, mapValue);//当前指标值,如果当前指标涉及到多个元素计算，那么结果就是多元素数据计算的值，如果不涉及，就是其本身的值

                    escalationData.getDynamicColumns().putIfAbsent(entity.getIndexName(), indexValue);

                }
                result.add(escalationData);
            }
        }

        return result;
    }

    private List<ClinicalGatherDataDto> queryData(QueryEscalation queryEscalation) {
        List<String> times = queryEscalation.getTimes();
        String s1 = times.get(0);
        List<ClinicalGatherDataDto> result = new ArrayList<>();
        //查询指标表中的所有的关于上报信息的元素定义公式 todo 后续查询where条件补充，只查询指标上报
        List<IndicatorDataEntity> list = indicatorDataMapper.selectAll(queryEscalation);
        //todo 分页插件超过最后一页了，结果还是会默认查询最后一页，先暂时这样 这里是分页插件的问题，后续有空看怎么改合适
        List<IndicatorDataEntity> count = indicatorDataMapper.selectAll(queryEscalation);
        if (count.size() < (queryEscalation.getPageSize() * queryEscalation.getPageNumber())) {
            return null;
        }
        deptGatherService.fillTime(queryEscalation);
        List<String> elementIds = gatherCommonService.getAllElementIds(list);
        //查询元素定义表，确定元素数据来源
        List<ElementDataEntity> elementDataEntities = elementDataMapper.query(elementIds);
        //分别得出天表，月表，手填表的元素数据
        List<ElementDataEntity> dayTable = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && "1".equals(s.getDataTable())).collect(Collectors.toList());
        List<ElementDataEntity> monthTable = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && "2".equals(s.getDataTable())).collect(Collectors.toList());
        List<ElementDataEntity> handTable = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && "3".equals(s.getDataTable())).collect(Collectors.toList());
        List<DepartmentIndicatorEntity> dayData = new ArrayList<>();
        if (!org.springframework.util.CollectionUtils.isEmpty(dayTable)) {
            queryEscalation.setElementIds(dayTable.stream().map(ElementDataEntity::getId).collect(Collectors.toList()));
            dayData = elementDataDayMapper.queryEscalation(queryEscalation); //天表数据
        }
        List<DepartmentIndicatorEntity> monthData = new ArrayList<>();
        if (s1.length() != 10) {
            if (!org.springframework.util.CollectionUtils.isEmpty(monthTable)) {
                queryEscalation.setElementIds(dayTable.stream().map(ElementDataEntity::getId).collect(Collectors.toList()));
                monthData = elementDataMonthMapper.queryEscalation(queryEscalation); //月表数据
            }
        }

        Map<String, List<DepartmentIndicatorEntity>> dayMap = dayData.stream().filter(s -> s.getId() != null).collect(Collectors.groupingBy(DepartmentIndicatorEntity::getId));
        Map<String, List<DepartmentIndicatorEntity>> monthMap = monthData.stream().filter(s -> s.getId() != null).collect(Collectors.groupingBy(DepartmentIndicatorEntity::getId));
        dayMap = null == dayMap ? new HashMap<>() : dayMap;
        monthMap = null == monthMap ? new HashMap<>() : monthMap;
        for (IndicatorDataEntity entity : list) {
            //构建EscalationData对象
            ClinicalGatherDataDto escalationData = new ClinicalGatherDataDto();
            escalationData.setIndicatorName(entity.getIndexCode() + entity.getIndexName());
            escalationData.setUnit(entity.getIndexUnit());
            escalationData.setRow(entity.getRank());
            //todo 如果是手填指标，就要查询手填表 不是手填指标才根据公式计算
            //根据ids求出元素表中的元素，然后代入计算公式中解析
            if (StringUtils.isNotBlank(entity.getIds())) {
                //指标的计算公式
                String calculationFormulaId = entity.getCalculationFormulaId();
                List<DepartmentIndicatorEntity> elementDays = new ArrayList<>();
                String[] ids = entity.getIds().split(",");
                for (String id : ids) {
                    if (!org.springframework.util.CollectionUtils.isEmpty(dayMap.get(id))) {
                        List<DepartmentIndicatorEntity> mapValues = dayMap.get(id);
                        elementDays.addAll(mapValues);
                    } else if (!org.springframework.util.CollectionUtils.isEmpty(monthMap.get(id))) {
                        List<DepartmentIndicatorEntity> mapValues = monthMap.get(id);
                        elementDays.addAll(mapValues);
                    }
                }
                CalculatorUtils.calculator(elementDays, calculationFormulaId, escalationData, queryEscalation);
            }
            //如果escalationData.getDynamicColumns() 为空或者长度比queryEscalation.size要短，就补上
            if (escalationData.getDynamicColumns().isEmpty() || escalationData.getDynamicColumns().size() < times.size()) {
                List<String> time = times;
                for (String s : time) {
                    escalationData.getDynamicColumns().putIfAbsent(s, new HeaderDataDto("-", "-", "-"));
                }
            }

            Map<String, HeaderDataDto> dynamicColumns = escalationData.getDynamicColumns();

            //同月内
            if (times.get(0).substring(0, 7).equals(times.get(times.size() - 1).substring(0, 7))) {
                Map<String, HeaderDataDto> resultMap = new LinkedHashMap<>();
                BigDecimal indicator = BigDecimal.ZERO;
                BigDecimal yoyValue = BigDecimal.ZERO;
                BigDecimal momValue = BigDecimal.ZERO;
                for (String key : dynamicColumns.keySet()) {
                    HeaderDataDto headerDataDto = dynamicColumns.get(key);
                    indicator = indicator.add(new BigDecimal("-".equals(headerDataDto.getIndicator()) ? "0" : headerDataDto.getIndicator()));
                    yoyValue = yoyValue.add(new BigDecimal("-".equals(headerDataDto.getYoyValue()) ? "0" : headerDataDto.getYoyValue()));
                    momValue = momValue.add(new BigDecimal("-".equals(headerDataDto.getMomValue()) ? "0" : headerDataDto.getMomValue()));
                }

                log.info("时间groupKey={},totalIndicator={}", times.get(0), indicator);
                indicator = indicator.divide(new BigDecimal(dynamicColumns.keySet().size()), 4, RoundingMode.HALF_UP);
                yoyValue = yoyValue.divide(new BigDecimal(dynamicColumns.keySet().size()), 4, RoundingMode.HALF_UP);
                momValue = momValue.divide(new BigDecimal(dynamicColumns.keySet().size()), 4, RoundingMode.HALF_UP);

                resultMap.put(times.get(0).substring(0, 7), new HeaderDataDto(indicator.toString(), yoyValue.toString(), momValue.toString()));
                escalationData.setDynamicColumns(resultMap);
            } else {
                //不在同一个月类，分组聚合
                //创建一个 Map 用于按照 key 的子字符串进行分组
                Map<String, List<HeaderDataDto>> groupedMap = new HashMap<>();

                // 2. 遍历 dynamicColumns 中的每个条目，将其放入相应的分组中
                for (Map.Entry<String, HeaderDataDto> entry : dynamicColumns.entrySet()) {
                    String key = entry.getKey().substring(0, 7); // 获取 key 的子字符串作为分组依据
                    HeaderDataDto value = entry.getValue();
                    groupedMap.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
                }

                // 3. 对每个分组中的 HeaderDataDto 进行平均值计算
                Map<String, HeaderDataDto> averages = new HashMap<>();
                for (Map.Entry<String, List<HeaderDataDto>> entry : groupedMap.entrySet()) {
                    String groupKey = entry.getKey();
                    List<HeaderDataDto> dataList = entry.getValue();

                    // 计算平均值
                    double totalIndicator = 0.0;
                    double totalYoyValue = 0.0;
                    double totalMomValue = 0.0;
                    int sum = 0;
                    for (HeaderDataDto dto : dataList) {
                        totalIndicator += Double.parseDouble(dto.getIndicator().equals("-") ? "0" : dto.getIndicator()); // 这里假设 HeaderDataDto 有一个名为 getIndicator 的方法用于获取 indicator 值
                        totalYoyValue += Double.parseDouble(dto.getYoyValue().equals("-") ? "0" : dto.getYoyValue()); // 这里假设 HeaderDataDto 有一个名为 getIndicator 的方法用于获取 indicator 值
                        totalMomValue += Double.parseDouble(dto.getMomValue().equals("-") ? "0" : dto.getMomValue()); // 这里假设 HeaderDataDto 有一个名为 getIndicator 的方法用于获取 indicator 值
                        sum++;
                    }
                    double averageIndicator = totalIndicator / sum;
                    double avgTotalYoyValue = totalYoyValue / sum;
                    double avgTotalMomValue = totalMomValue / sum;
                    log.info("时间groupKey={},totalIndicator={}", groupKey, totalIndicator);
                    HeaderDataDto headerDataDto = new HeaderDataDto(averageIndicator + "", avgTotalYoyValue + "", avgTotalMomValue + "");
                    averages.put(groupKey, headerDataDto);
                    escalationData.setDynamicColumns(averages);
                }
            }
            result.add(escalationData);
        }
        return result;
    }

    public void export(QueryEscalation queryEscalation, HttpServletResponse response) {
        List<ClinicalGatherDataDto> clinicalGatherDataDtos = queryClinicalData(queryEscalation);
        dataProcess(clinicalGatherDataDtos);
        ExcelUtilsPlus.export(clinicalGatherDataDtos, ClinicalGatherDataDto.class, response, queryEscalation);
    }

    public void exportClinicalData(QueryEscalation queryEscalation, HttpServletResponse response) {
        List<ClinicalGatherDataDto> clinicalGatherDataDtos = (List<ClinicalGatherDataDto>) queryClinicalIndicatorData(queryEscalation).getList();
        dataProcess(clinicalGatherDataDtos);
        ExcelUtilsPlus.exportDeptData(clinicalGatherDataDtos, ClinicalGatherDataDto.class, response, queryEscalation);
    }

    private void dataProcess(List<ClinicalGatherDataDto> clinicalGatherDataDtos) {
        if (!org.apache.commons.collections4.CollectionUtils.isEmpty(clinicalGatherDataDtos)) {
            clinicalGatherDataDtos = clinicalGatherDataDtos.stream().filter(s -> StringUtils.isNotBlank(s.getUnit())).collect(Collectors.toList());
            for (ClinicalGatherDataDto data : clinicalGatherDataDtos) {
                for (String key : data.getDynamicColumns().keySet()) {
                    HeaderDataDto headerDataDto = data.getDynamicColumns().get(key);
                    String value = headerDataDto.getIndicator();
                    if (data.getUnit().contains("%") && value.matches(regex)) {
                        headerDataDto.setIndicator(new BigDecimal(value).multiply(new BigDecimal(100)).setScale(4, RoundingMode.HALF_UP) + "%");
                    } else if (value.matches(regex)) {
                        headerDataDto.setIndicator(new BigDecimal(value).setScale(4, RoundingMode.HALF_UP) + "");
                    }
                    if (headerDataDto.getMomValue() != null && headerDataDto.getMomValue().matches(regex)) {
                        headerDataDto.setMomValue(new BigDecimal(headerDataDto.getMomValue()).setScale(4, RoundingMode.HALF_UP) + "");
                    }
                    if (headerDataDto.getYoyValue() != null && headerDataDto.getYoyValue().matches(regex)) {
                        headerDataDto.setYoyValue(new BigDecimal(headerDataDto.getYoyValue()).setScale(4, RoundingMode.HALF_UP) + "");
                    }
                }
            }
        }
    }

    public List<ClinicalGatherDataDto> queryClinicalDataTest(QueryEscalation queryEscalation) {
        //直接查大指标有哪些
        List<IndicatorDataEntity> list = indicatorDataMapper.queryMajorIndicator(queryEscalation);
        List<String> elementIds = getAllElementIds(list);
        //查询元素定义表，确定元素数据来源
        List<ElementDataEntity> elementDataEntities = elementDataMapper.query(elementIds);
        Map<String, Map<String, List<DepartmentIndicatorEntity>>> dayMap = getData(elementDataEntities, "1", queryEscalation); //天表数据
        Map<String, Map<String, List<DepartmentIndicatorEntity>>> monthMap = getData(elementDataEntities, "2", queryEscalation); //月表数据
        Map<String, Map<String, List<DepartmentIndicatorEntity>>> handMap = getData(elementDataEntities, "3", queryEscalation); //填报表数据
        return null;
    }

    /**
     * 查询指标（元素）在总的元素ids
     *
     * @param list
     * @return
     */
    public List<String> getAllElementIds(List<IndicatorDataEntity> list) {
        if (org.springframework.util.CollectionUtils.isEmpty(list)) {
            return null;
        }
        //把list里面的ids全部单拎出来，去重，然后查询把所有的元素id查出来 但是还是要分月表，天表，手填表 所以数据源list应该分类，暂时只考虑天表，月表
        List<String> elementIds = new ArrayList<>();
        for (IndicatorDataEntity indicatorDataEntity : list) {
            if (StringUtils.isNotBlank(indicatorDataEntity.getIds())) {
                String[] split = indicatorDataEntity.getIds().split(",");
                elementIds.addAll(Arrays.asList(split));
            }
        }
        if (elementIds.isEmpty()) {
            return null;
        }
        elementIds = elementIds.stream().distinct().collect(Collectors.toList());
        return elementIds;
    }

    public Map<String, Map<String, List<DepartmentIndicatorEntity>>> getData(List<ElementDataEntity> elementDataEntities, String dataTable, QueryEscalation queryEscalation) {
        //分别得出天表，月表，手填表的元素数据
        List<ElementDataEntity> tableData = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && dataTable.equals(s.getDataTable())).collect(Collectors.toList());
        List<DepartmentIndicatorEntity> data = new ArrayList<>();
        if (!CollectionUtils.isEmpty(tableData)) {
            queryEscalation.setElementIds(tableData.stream().map(ElementDataEntity::getId).collect(Collectors.toList()));
            if ("1".equals(dataTable)) {
                log.info("查询实际数据的元素id为:{}", queryEscalation.getElementIds());
                data = elementDataDayMapper.queryEscalationDept(queryEscalation); //天表数据
            } else if ("2".equals(dataTable)) {
                if (queryEscalation.getTimes().get(0).length() != 10) {
                    data = elementDataMonthMapper.queryEscalationDept(queryEscalation); //月表数据
                }
            }
        }
        //将数据的deptName做成最外层的key，id做成内层的key Map<String,Map<String, List<DepartmentIndicatorEntity>>>
        return data.stream().filter(s -> null != s.getDeptName() && null != s.getId())
                .collect(Collectors.groupingBy(DepartmentIndicatorEntity::getDeptName,
                        Collectors.groupingBy(DepartmentIndicatorEntity::getId)));
    }
}
